package com.ywk.base.bitOperation;

import java.util.Arrays;

/**
 *机器数的第一位是符号位，后边才是真正的数值
 *例：8位二进制 [1111 1111,0111 1111]->[-127,127]
 *
 *
 *正数：原码，反码，补码不变
 *负数：原码取反（符号位不变，其余位取反）得反码，反码+1得补码
 *
 * 位运算：两个或多个数值进行位运时需要将原码转成补码，然后补码间进行位运算得补码，最后补码符号位0为正数直接就是原码，补码符号位1为负数，需要-1取反得原码
 * byte、short、char 在使用位运算时按照 int 类型处理，即32位处理，在进行下面前6种运算时，数值不大，可用8,或16位来运算，但是当运算符为 >>> 时必须采用32位运算，
 * 因为无符号数右移不能保证符号位不变
 *
 * 运算符：
 * 1. &：与，两个位都为1时，结果才为1
 * 2. |：或，两个位都为0时，结果才为0
 * 3. ^：[异或](https://so.csdn.net/so/search?q=异或&spm=1001.2101.3001.7020)，两个位相同为0，相异为1
 * 4. ~：[取反](https://so.csdn.net/so/search?q=取反&spm=1001.2101.3001.7020)，0->1 1->0
 * 5. <<：左移，各二进位全部左移若干位，高位丢弃，低位补0
 * 6. >>：右移，各二进位全部右移若干位，符号位1，高位补1，符号位0 ，高位补0（保证符号位不变），低位都是丢弃
 * 7. >>>：无符号数右移，各二进位全部右移若干位，高位补0,低位丢弃
 *
 * @Author zbh
 * @Date 2023/3/27
 */
public class BitOperationDemo {

    public static void main(String[] args) {
        //0000 0011 & 0000 0010 =0000 0010
        System.out.println("3&2="+(3&2));

        //-3的补码=原码1000 0011取反得1111 1100再+1得 1111 1101，运算 1111 1101 & 0000 0010 =0000 0000 -> 符号位0为正数直接转十进制为0
        System.out.println("-3&2="+(-3&2));

        //-3八位原码：1000 0011 -> 反码：1111 1100 -> 1111 1101，-2八位原码：1000 0010 ->反码：1111 1101 -> 补码：1111 1110
        // 1111 1101 & 1111 1110 =1111 1110 -> 此时计算结果补码为 1111 1100，符号位1负数，负数补码转原码需要-1取反，-1得 1111 1011，取反得1000 0100 -> -4
        System.out.println("-3&-2="+(-3&-2));
        //-3三十二位原码：1000 0000 0000 0000 0000 0000 0000 0011， 补码：1111 1111 1111 1111 1111 1111 1111 1101
        //-2三十二位原码：1000 0000 0000 0000 0000 0000 0000 0010，补码：1111 1111 1111 1111 1111 1111 1111 1110
        // 1111 1111 1111 1111 1111 1111 1111 1101 & 1111 1111 1111 1111 1111 1111 1111 1110 = 1111 1111 1111 1111 1111 1111 1111 1100
        // 1111 1111 1111 1111 1111 1111 1111 1100 -> 原码:1000 0000 0000 0000 0000 0000 0000 0100 -> -4
        //8位和32位计算结果都一样


        //0000 0011 | 0000 0010 = 0000 0011
        System.out.println("3|2="+(3|2));

        //0000 0011 ^ 0000 0010 = 0000 0001
        System.out.println("3^2="+(3^2));

        //~0000 0011 = 1111 1100 -> 此时计算结果补码为 1111 1100，符号位1负数，负数补码转原码需要-1取反，-1得 1111 1011，取反得1000 0100
        System.out.println("~3="+(~3));

        //-3原码1000 0011，反码1111 1100，补码为1111 1101，~1111 1101  = ,0000 0010 -> 此时计算结果补码为 0000 0010 -> 2
        System.out.println("~-3="+(~-3));

        //~0000 0010 = 1111 1101 -> 此时计算结果补码为 1111 1101，符号位1负数，负数补码转原码需要-1取反，-1得 1111 1100，取反得1000 0011
        System.out.println("~2="+(~2));

        //将3的二进制位左移2位，0000 0011左移2位为0000 1100 -> 12
        System.out.println("3<<2="+(3<<2));

        //-3原码1000 0011，反码1111 1100，补码为1111 1101,将3的二进制位补码左移2位得 1111 0100 -> -1得反码 1111 0011 —> 取反得原码 1000 1100 -> -12
        System.out.println("-3<<2="+(-3<<2));

        //-3原码1000 0011，反码1111 1100，补码为1111 1101,将3的二进制位补码右移2位得 1111 1111 -> -1得反码 1111 1110 —> 取反得原码 1000 0001 -> -1
        System.out.println("-3>>2="+(-3>>2));

        //-3原码1000 0011，反码1111 1100，补码为1111 1101,将3的二进制位补码无符号右移2位得 0011 1111 -> 63 按8位运算是不对的，真实值为1073741823
        System.out.println("-3>>>2="+(-3>>>2));

        System.out.println(Arrays.toString(toBytes(255)));
        System.out.println(0xff);
        //0000 0000 0000 0000 0000 0000 0111 1111
    }

    /**
     * int转byte数组
     * 0xff代表二进制的1111 1111
     * @param number
     * @return
     */
    public static byte[] toBytes(int number){//1000 0001 1111 1111
        byte[] bytes = new byte[4];
        bytes[3] = (byte)number;
        bytes[2] = (byte) ((number >> 8) & 0xFF);
        bytes[1] = (byte) ((number >> 16) & 0xFF);
        bytes[0] = (byte) ((number >> 24) & 0xFF);
        return bytes;
    }

}
